﻿using System;
using System.Configuration;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace Slippor.Douban.Radio.Assist
{
    public static class RadioUtility
    {
        [DllImport("GDI32 ", CharSet = CharSet.Auto)]
        public static extern int GetPixel(IntPtr hWnd, int x, int y);

        #region 清理内存
        [DllImport("kernel32.dll")]
        private static extern int SetProcessWorkingSetSize(IntPtr hProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
        private static int SetProcessMemoryToMin(IntPtr SetProcess)
        {
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                return SetProcessWorkingSetSize(SetProcess, -1, -1);
            }
            return -1;
        }
        private static int SetProcessMemoryToMin()
        {
            return SetProcessMemoryToMin(Process.GetCurrentProcess().Handle);
        }

        private static readonly object _forLock = new object();
        public static void ReleaseMemory()
        {
            lock (_forLock)
            {
                SetProcessMemoryToMin();
            }
        }
        #endregion

        public static IntPtr GetHandler(IntPtr handler, String classNameString)
        {
            var className = new StringBuilder(100);
            while (className.ToString() != classNameString)
            {
                handler = GetWindow(handler, 5); // Get a handle to the child window
                GetClassName(handler, className, className.Capacity);
            }
            return handler;
        }

        public static void SetConfig(String key, object value)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (ConfigurationManager.AppSettings[key] == null)
            {
                config.AppSettings.Settings.Add(key, value.ToString());
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection(config.AppSettings.SectionInformation.Name);
            }
            else if (config.AppSettings.Settings[key].Value != value.ToString())
            {
                config.AppSettings.Settings[key].Value = value.ToString();
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection(config.AppSettings.SectionInformation.Name);
            }
        }

        public static void Browse(String url)
        {
            try
            {
                Process.Start(url);
            }
            catch
            {
                Process.Start("IEXPLORE.EXE", url);
            }
        }

        #region 操作Flash
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

        [DllImport("user32.dll ")]
        public extern static IntPtr GetDC(IntPtr hWnd);

        [DllImport("user32", CharSet = CharSet.Auto)] //确定坐标
        public static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);

        private const uint WM_MOUSEMOVE = 0x200;
        private const uint WM_LBUTTONDOWN = 0x201; // Left click down code
        private const uint WM_LBUTTONUP = 0x202; // Left click up code

        public static void ControlFlash(IntPtr handler, int x, int y)
        {
            IntPtr lParam = (IntPtr)((y << 16) | x); // The coordinates
            IntPtr wParam = IntPtr.Zero; // Additional parameters for the click (e.g. Ctrl)

            SendMessage(handler, WM_MOUSEMOVE, wParam, lParam); // Mouse   Move
            SendMessage(handler, WM_LBUTTONDOWN, wParam, lParam); // Mouse button down
            SendMessage(handler, WM_LBUTTONUP, wParam, lParam); // Mouse button up
        }
        #endregion

        #region 静音
        private const int FEATURE_DISABLE_NAVIGATION_SOUNDS = 21;
        private const int SET_FEATURE_ON_THREAD = 0x00000001;
        private const int SET_FEATURE_ON_PROCESS = 0x00000002;
        private const int SET_FEATURE_IN_REGISTRY = 0x00000004;
        private const int SET_FEATURE_ON_THREAD_LOCALMACHINE = 0x00000008;
        private const int SET_FEATURE_ON_THREAD_INTRANET = 0x00000010;
        private const int SET_FEATURE_ON_THREAD_TRUSTED = 0x00000020;
        private const int SET_FEATURE_ON_THREAD_INTERNET = 0x00000040;
        private const int SET_FEATURE_ON_THREAD_RESTRICTED = 0x00000080;

        [DllImport("urlmon.dll")]
        [PreserveSig]
        [return: MarshalAs(UnmanagedType.Error)]
        static extern int CoInternetSetFeatureEnabled(int FeatureEntry,[MarshalAs(UnmanagedType.U4)] int dwFlags,bool fEnable);

        public static void MuteNavigation()
        {
            int feature = FEATURE_DISABLE_NAVIGATION_SOUNDS;
            CoInternetSetFeatureEnabled(feature, SET_FEATURE_ON_PROCESS, true);
        }
        #endregion

        public static String VerifyText(String text)
        {
            if(text.Length > 64)
            {
                text = text.Substring(0, 64);
            }
            return text;
        }

        public static string VerifyRegex(String text)
        {
            MatchEvaluator regexEvaluator = new MatchEvaluator(JustifyRegex);
            text = Regex.Replace(text, @"[\*+?.\[\]{}()^|$]", regexEvaluator);
            return text;
        }

        public static String JustifyRegex(Match m)
        {
            return @"\" + m.Value;
        }

        #region 操作Cookie
        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool InternetSetCookie(string lpszUrlName, string lbszCookieName, string lpszCookieData);

        [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool InternetGetCookie(string lpszUrlName, string lbszCookieName, StringBuilder lpszCookieData, ref int lpdwSize);

        [DllImport("kernel32.dll")]
        public static extern Int32 GetLastError();


        public static String GetCookie(String url,String name)
        {
            int size = 1000;
            StringBuilder cookie = new StringBuilder(size);
            if (!InternetGetCookie(url, name, cookie, ref size))
            {
                throw(new Exception(GetLastError().ToString()));
            }
            else
            {
                return cookie.ToString();
            }
        }
        #endregion

        #region 切换IE代理
        [DllImport("wininet.dll", SetLastError = true)]
        private static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int lpdwBufferLength);

        public static void RefreshIESettings(string strProxy)
        {
            const int INTERNET_OPTION_PROXY = 38;
            const int INTERNET_OPTION_SETTINGS_CHANGED = 39;
            const int INTERNET_OPEN_TYPE_PROXY = 3;
            const int INTERNET_OPEN_TYPE_DIRECT = 1;

            Struct_INTERNET_PROXY_INFO struct_IPI;

            // Filling in structure 
            if (String.IsNullOrEmpty(strProxy))
            {
                struct_IPI.dwAccessType = INTERNET_OPEN_TYPE_DIRECT;
            }
            else
            {
                struct_IPI.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
            }
            struct_IPI.proxy = Marshal.StringToHGlobalAnsi(strProxy);
            struct_IPI.proxyBypass = Marshal.StringToHGlobalAnsi("local");

            // Allocating memory 
            IntPtr intptrStruct = Marshal.AllocCoTaskMem(Marshal.SizeOf(struct_IPI));

            // Converting structure to IntPtr 
            Marshal.StructureToPtr(struct_IPI, intptrStruct, true);

            bool iReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_PROXY, intptrStruct, Marshal.SizeOf(struct_IPI));
            InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
        }
        #endregion
    }

    public struct Struct_INTERNET_PROXY_INFO
    {
        public int dwAccessType;
        public IntPtr proxy;
        public IntPtr proxyBypass;
    }
}